<template>
  <draw-component
    :drawer-visible="state.show"
    size="460px"
    title="新增/编辑角色"
    @close-drawer="handleClose"
    @save-drawer="handleSubmit"
  >
    <el-form
      ref="formRef"
      :model="state.formData"
      :rules="state.formRules"
      label-width="90px"
      class="my-form-box2"
    >
      <el-form-item label="角色名称:" prop="roleName">
        <el-input v-model="state.formData.roleName" placeholder="请输入角色名称"></el-input>
      </el-form-item>
      <el-form-item class="tree-box" label="菜单权限:" prop="menuIds">
        <div class="df ais">
          <div class="permission-tree">
            <el-checkbox v-model="state.caseCheckAll" class="check-tree" @change="handleCheckAllChange"
              >全选</el-checkbox
            >
            <el-tree
              ref="treeRef"
              :data="state.permissionOptions"
              :props="state.props"
              :check-strictly="state.checkStrictly"
              :default-expand-all="false"
              show-checkbox
              node-key="permissionId"
              @check-change="handleTreeChange"
            />
          </div>
          <div class="text-box df aic" @click="handleCollapse">
            <template v-if="!state.collapse">
              <div class="text">展开</div>
              <i-ep-arrow-down></i-ep-arrow-down>
            </template>
            <template v-else>
              <div class="text">收起</div>
              <i-ep-arrow-up></i-ep-arrow-up>
            </template>
          </div>
        </div>
      </el-form-item>
    </el-form>
  </draw-component>
</template>

<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus'
import { editSubmit, addSubmit, validateNameExist, getRoleDetailById } from '../api'
import { useProxy } from '@/utils/proxy'
const validateName = async (rule: any, value: any, callback: any) => {
  if (!value) return callback()
  const { data } = await validateNameExist<boolean>({
    roleName: value,
    roleId: state.currRoleId || null
  })
  if (!data) {
    callback(new Error('角色名称重复'))
  } else {
    callback()
  }
}
const emit = defineEmits(['handleAdded'])
const { proxy } = useProxy()
const formRef = ref<FormInstance>()
const treeRef = ref()
const state = reactive({
  caseCheckAll: false, //控制全选
  checkStrictly: false, //控制是否严格父子节点不关联
  collapse: false, //控制展开收起
  currRoleId: '',
  show: false,
  isSubmiting: false,
  formData: {
    menuIds: [],
    roleName: ''
  },
  formRules: {
    roleName: [
      { required: true, message: '请输入名称', trigger: 'blur' },
      { max: 64, message: '输入字符不得超过64位', trigger: 'blur' },
      { validator: validateName, trigger: 'blur' }
    ]
  } as FormRules,
  permissionOptions: [],
  props: {
    label: 'permissionName',
    children: 'children'
  }
})
// 全选
const handleCheckAllChange = () => {
  if (state.caseCheckAll) {
    let arrID: string[] = []
    getTreeItemId(state.permissionOptions, arrID)
    treeRef.value.setCheckedKeys(arrID)
  } else {
    treeRef.value.setCheckedKeys([])
  }
}
// 树节点选择回调
const handleTreeChange = (data: any, check: boolean) => {
  if (!check) state.caseCheckAll = false
}
// 展开关闭树
const handleCollapse = () => {
  state.collapse = !state.collapse
  isUnfold(state.permissionOptions, state.collapse)
}
// 遍历树获取id
const getTreeItemId = (data: any, arr: string[]) => {
  data.forEach((el: any) => {
    arr.push(el.permissionId)
    if (el.children && el.children.length > 0) {
      getTreeItemId(el.children, arr)
    }
  })
  return arr
}
// 全部展开or收起
const isUnfold = (data: any, flag: boolean) => {
  data.forEach((el: any) => {
    treeRef.value.store.nodesMap[el.id].expanded = flag
    if (el.children && el.children.length > 0) {
      isUnfold(el.children, flag)
    }
  })
}

// 关闭回调
const handleClose = () => {
  state.currRoleId = ''
  state.collapse = false
  state.caseCheckAll = false
  state.formData = {
    menuIds: [],
    roleName: ''
  }
  state.show = false
}
// 保存
const handleSubmit = async () => {
  await formRef.value?.validate(async (valid) => {
    if (valid) {
      if (state.isSubmiting) return
      state.isSubmiting = true
      const selectFuncAry = treeRef.value.getCheckedKeys()
      const selectHalfAry = treeRef.value.getHalfCheckedKeys()
      const menuIds = selectFuncAry.concat(selectHalfAry)
      if (state.currRoleId) {
        editSubmit(state.currRoleId, { roleName: state.formData.roleName, menuIdList: menuIds })
          .then(() => {
            proxy.$message.msgSuccess('编辑成功')
            state.isSubmiting = false
            handleClose()
            emit('handleAdded')
          })
          .catch(() => {
            state.isSubmiting = false
          })
      } else {
        addSubmit({ roleName: state.formData.roleName, menuIdList: menuIds })
          .then(() => {
            proxy.$message.msgSuccess('新增成功')
            state.isSubmiting = false
            handleClose()
            emit('handleAdded')
          })
          .catch(() => {
            state.isSubmiting = false
          })
      }
    }
  })
}
// 获取权限树
const getPermissionList = async () => {
  let { data } = await proxy.$api.menuList<any>()
  state.permissionOptions = data || []
}
// 获取详情
const getRoleDetail = async () => {
  let { data } = await getRoleDetailById<any>(state.currRoleId)
  const form = {} as any
  Object.keys(state.formData).forEach((item, index) => {
    if (item == 'menuIds') {
      form[item] =
        data.roleMenuResponseDtoList?.length > 0 ? getTreeItemId(data.roleMenuResponseDtoList, []) : []
    } else {
      form[item] = data[item] ?? ''
    }
  })
  state.formData = form
  let allArrID = getTreeItemId(state.permissionOptions, [])
  if (allArrID.length == state.formData.menuIds.length) state.caseCheckAll = true
  if (state.formData.menuIds.length > 0) {
    state.checkStrictly = true
    nextTick(() => {
      treeRef.value.setCheckedKeys(state.formData.menuIds)
      state.checkStrictly = false
    })
  }
}
getPermissionList()
defineExpose({ state, getRoleDetail })
</script>

<style lang="scss" scoped>
.check-tree {
  margin-left: 24px;
}
.tree-box {
  :deep(.el-form-item__content) {
    width: 240px;
  }
  .text-box {
    margin-top: 10px;
    color: $blue;
    cursor: pointer;
    margin-left: 5px;
    white-space: nowrap;
    .text {
      margin-right: 3px;
    }
  }
  .permission-tree {
    width: 240px;
    border-radius: 4px 4px 4px 4px;
    border: 1px solid #cccccc;
    min-height: 300px;
    overflow: auto;
    margin-top: 10px;
    :deep(.el-tree) {
      margin-top: -5px;
    }
  }
}
</style>
